import {NextResponse, NextRequest} from "next/server";
import {jwtDecode} from "jwt-decode";

const API_REFRESH_TOKEN_URL = "http://localhost:8000/auth/refresh";

export async function middleware(request: NextRequest) {
    const {pathname} = request.nextUrl;
    const accessToken = request.cookies.get('access_token')?.value;
    const refreshToken = request.cookies.get('refresh_token')?.value;
    console.log("middleware:", accessToken);

    // 1、放行公开路由（无需认证）
    const publicPaths = ["/login"];
    if (publicPaths.includes(pathname)) {
        return NextResponse.next();
    }

    // 2、无token跳转登录
    if (!accessToken || !refreshToken) {
        return NextResponse.redirect(new URL("/login", request.url));
    }

    // 3、检查access token是否过期
    try {
        const {exp} = jwtDecode(accessToken);
        const isExpired = exp * 1000 < Date.now();

        // Token 有效 继续访问
        if (!isExpired) {
            return NextResponse.next();
        }

        // Token过期 尝试刷新
        const refreshResponse = await fetch(API_REFRESH_TOKEN_URL, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "Authorization": `Bearer ${refreshToken}`
            },
            body: JSON.stringify({})
        });

        if (refreshResponse.ok) {
            const {access_token} = await refreshResponse.json();

            // 更新cookie并继续请求
            const response = NextResponse.next();
            response.cookies.set("access_token", access_token, {
                httpOnly: true,
                maxAge: 60 * 15
            });
            return response;
        }
    } catch (error) {
        console.log("Token 验证失败", error);
    }

    // 4、刷新失效或token无效 清除cookie并跳转登录
    const response = NextResponse.redirect(new URL("/login", request.url));
    response.cookies.delete('access_token');
    response.cookies.delete('refresh_token');
    return response;
}

// 配置中间件生效的路由（可选）
export const config = {
    matcher: ['/((?!_next/static|favicon.ico).*)'], // 匹配所有路由，排除静态文件
};
